package roles

import (
	"context"
	"fmt"
	"time"

	"github.com/google/uuid"
	"github.com/sirupsen/logrus"

	"xagent/internal/actor"
	proto "xagent/proto/v1"
)

// NovelOutline 表示小说大纲
type NovelOutline struct {
	ID         string
	Title      string
	Genre      string
	Target     string
	Background string
	MainPlot   string
	Subplots   []string
	Characters []string
	Conflicts  []string
	Chapters   []ChapterOutline
	CreatedAt  time.Time
	UpdatedAt  time.Time
}

// ChapterOutline 表示章节大纲
type ChapterOutline struct {
	ID         string
	Title      string
	Summary    string
	KeyEvents  []string
	Characters []string
	Setting    string
	WordCount  int
}

// StoryPlanner 表示故事规划者角色
type StoryPlanner struct {
	*actor.BaseActor
	outlines map[string]*NovelOutline
	logger   *logrus.Logger
}

// NewStoryPlanner 创建新的故事规划者
func NewStoryPlanner() *StoryPlanner {
	baseActor := actor.NewBaseActor(
		"story_planner",
		"StoryPlanner",
		"负责故事大纲和情节规划",
	)

	sp := &StoryPlanner{
		BaseActor: baseActor,
		outlines:  make(map[string]*NovelOutline),
		logger:    logrus.New(),
	}

	// 注册动作
	sp.AddAction(&CreateOutlineAction{sp})
	sp.AddAction(&DesignPlotAction{sp})
	sp.AddAction(&PlanChaptersAction{sp})

	return sp
}

// Action 实现
type CreateOutlineAction struct {
	sp *StoryPlanner
}

func (a *CreateOutlineAction) Name() string {
	return "create_outline"
}

func (a *CreateOutlineAction) Prerequisites() []string {
	return nil
}

func (a *CreateOutlineAction) Run(ctx context.Context, input interface{}) (*proto.AgentMessage, error) {
	task, ok := input.(*proto.Task)
	if !ok {
		return nil, fmt.Errorf("invalid input type")
	}

	// 思考大纲设计
	thought, err := a.sp.Think(ctx, fmt.Sprintf("设计小说大纲: %s", task.Description))
	if err != nil {
		return nil, err
	}

	// 创建大纲
	outline := &NovelOutline{
		ID:         uuid.NewString(),
		Title:      task.Metadata["novel_name"],
		Genre:      task.Metadata["genre"],
		Target:     task.Metadata["target_readers"],
		Background: thought.Content,
		MainPlot:   thought.Plan[0],
		Subplots:   thought.Plan[1:],
		Characters: []string{},
		Conflicts:  []string{},
		Chapters:   []ChapterOutline{},
		CreatedAt:  time.Now(),
		UpdatedAt:  time.Now(),
	}

	a.sp.outlines[outline.ID] = outline

	return &proto.AgentMessage{
		Id:   uuid.NewString(),
		Type: proto.MessageType_MESSAGE_TYPE_RESPONSE,
		Content: &proto.AgentMessage_Message{
			Message: fmt.Sprintf("小说大纲创建完成: %s\n主要情节: %s", outline.ID, outline.MainPlot),
		},
		Metadata: map[string]string{
			"outline_id": outline.ID,
			"title":      outline.Title,
			"genre":      outline.Genre,
		},
	}, nil
}

type DesignPlotAction struct {
	sp *StoryPlanner
}

func (a *DesignPlotAction) Name() string {
	return "design_plot"
}

func (a *DesignPlotAction) Prerequisites() []string {
	return []string{"create_outline"}
}

func (a *DesignPlotAction) Run(ctx context.Context, input interface{}) (*proto.AgentMessage, error) {
	task, ok := input.(*proto.Task)
	if !ok {
		return nil, fmt.Errorf("invalid input type")
	}

	outlineID := task.Metadata["outline_id"]
	outline, ok := a.sp.outlines[outlineID]
	if !ok {
		return nil, fmt.Errorf("outline not found: %s", outlineID)
	}

	// 思考情节设计
	thought, err := a.sp.Think(ctx, fmt.Sprintf("设计情节: %s\n背景: %s", outline.Title, outline.Background))
	if err != nil {
		return nil, err
	}

	// 更新情节
	outline.Conflicts = thought.Plan
	outline.UpdatedAt = time.Now()

	return &proto.AgentMessage{
		Id:   uuid.NewString(),
		Type: proto.MessageType_MESSAGE_TYPE_RESPONSE,
		Content: &proto.AgentMessage_Message{
			Message: fmt.Sprintf("情节设计完成: %s\n主要冲突: %v", outline.ID, outline.Conflicts),
		},
		Metadata: map[string]string{
			"outline_id":      outline.ID,
			"conflicts_count": fmt.Sprintf("%d", len(outline.Conflicts)),
		},
	}, nil
}

type PlanChaptersAction struct {
	sp *StoryPlanner
}

func (a *PlanChaptersAction) Name() string {
	return "plan_chapters"
}

func (a *PlanChaptersAction) Prerequisites() []string {
	return []string{"design_plot"}
}

func (a *PlanChaptersAction) Run(ctx context.Context, input interface{}) (*proto.AgentMessage, error) {
	task, ok := input.(*proto.Task)
	if !ok {
		return nil, fmt.Errorf("invalid input type")
	}

	outlineID := task.Metadata["outline_id"]
	outline, ok := a.sp.outlines[outlineID]
	if !ok {
		return nil, fmt.Errorf("outline not found: %s", outlineID)
	}

	// 思考章节规划
	thought, err := a.sp.Think(ctx, fmt.Sprintf("规划章节: %s\n主要情节: %s\n冲突: %v",
		outline.Title, outline.MainPlot, outline.Conflicts))
	if err != nil {
		return nil, err
	}

	// 创建章节大纲
	for i, plan := range thought.Plan {
		chapter := ChapterOutline{
			ID:         uuid.NewString(),
			Title:      fmt.Sprintf("第%d章", i+1),
			Summary:    plan,
			KeyEvents:  []string{},
			Characters: []string{},
			Setting:    "",
			WordCount:  3000, // 预估字数
		}
		outline.Chapters = append(outline.Chapters, chapter)
	}

	outline.UpdatedAt = time.Now()

	return &proto.AgentMessage{
		Id:   uuid.NewString(),
		Type: proto.MessageType_MESSAGE_TYPE_RESPONSE,
		Content: &proto.AgentMessage_Message{
			Message: fmt.Sprintf("章节规划完成: %s\n总章节数: %d", outline.ID, len(outline.Chapters)),
		},
		Metadata: map[string]string{
			"outline_id":      outline.ID,
			"chapters_count":  fmt.Sprintf("%d", len(outline.Chapters)),
			"estimated_words": fmt.Sprintf("%d", len(outline.Chapters)*3000),
		},
	}, nil
}

// Helper methods
func (sp *StoryPlanner) GetOutline(id string) *NovelOutline {
	return sp.outlines[id]
}

func (sp *StoryPlanner) GetOutlineMetrics() map[string]interface{} {
	metrics := make(map[string]interface{})
	totalOutlines := len(sp.outlines)
	totalChapters := 0
	totalWords := 0

	for _, outline := range sp.outlines {
		totalChapters += len(outline.Chapters)
		for _, chapter := range outline.Chapters {
			totalWords += chapter.WordCount
		}
	}

	metrics["total_outlines"] = totalOutlines
	metrics["total_chapters"] = totalChapters
	metrics["total_words"] = totalWords
	metrics["average_chapter_length"] = float64(totalWords) / float64(totalChapters)

	return metrics
}
